home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-01-13 | 23.9 KB | 1,057 lines |
-
-
- -1-
-
-
-
-
-
- BOOLEAN OPERATIONS IN BASIC LANGUAGE
-
-
-
- It was like digging skeletons out of the closet. I knew
-
- that old college algebra book was somewhere, but we had just
-
- moved and all of the family's books were stored in no less
-
- than 24 sealed boxes. Of course, after hours of digging, I
-
- found it...in the next to the last box. For years I have
-
- used comparison and logical operations in my Basic programs
-
- without knowing the underlying theory; but if I was going to
-
- write an article to help beginner Basic programmers
-
- transition to intermediate programming, I'd better have a
-
- reference. Finally on page 236, I found a brief section on
-
- Boolean algebra.
-
- In the simple world of Boole, everything is either black or
-
- white; that is, it is either TRUE or FALSE. You can reduce a
-
- series of IF-THEN logical operations to a single line of code
-
- using Boolean algebra, thus adding speed to the program and
-
- reducing the length of the source code. The examples in this
-
- tutorial are written in the popular GFA BASIC, my favorite
-
- language for the ST series, but the ideas on Boolean
-
- comparisons can be universally applied to any Basic language
-
- program.
-
-
-
- BOOLEAN BASICS
-
-
-
- Boolean algebra looks at a mathematical comparison and
-
-
-
-
-
-
-
-
-
- -2-
-
-
-
- determines if it is TRUE or FALSE, and then assigns a value
-
- to the result. In GFA BASIC, TRUE = negative one(-1) and
-
- FALSE = zero(0). You have to be careful because all Basic
-
- languages are not identical. For example, in Atari-800
-
- Basic, TRUE = positive one(+1) and FALSE = zero(0).
-
- Let's begin with this mathematical comparison:
-
-
-
- X=12
-
-
-
- As a simple mathematical comparison function, X is equated
-
- to twelve. But in Boolean algebra, if X is equal to twelve,
-
- then the condition is TRUE and the statement is assigned the
-
- value of negative one; or if X is not equal to twelve, then
-
- the condition is FALSE and the statement is assigned the
-
- value of zero. Putting this into Basic code, consider the
-
- brief program below:
-
-
-
- Let X=5
-
- Let Y=5
-
- Z = (X=12) + (Y<10)
-
- Print "Z equals ";Z
-
-
-
- As a beginner basic programmer, comparing a variable (Z) to
-
- other comparison statements (X=12, Y<10) combined with
-
- arithmetic functions (plus sign) made me scratch my head
-
- because the equation looked like nonsense; but this is a
-
- classic basic Boolean operation. We know that X=5 and Y=5 by
-
-
-
-
-
-
-
-
-
- -3-
-
-
-
- previous initialization or calculation. So what does Z equal
-
- by Boolean algebra? X equals five, so (X=12) is FALSE and
-
- has a value of zero. Y also equals five, so (Y<10) is TRUE
-
- and has a value of negative one. Therefore, Z equals zero
-
- plus negative one for a total value of negative one.
-
- As demonstrated, you can utilize any of the comparison
-
- functions with Boolean algebra; equals (=), less than (<),
-
- greater than (>), not equal to (<>), greater than or equal to
-
- (>=), and less than or equal to (<=).
-
- If you haven't caught on to the potential power of Boolean
-
- operations yet, don't worry. You'll find that the following
-
- program examples and descriptive text will give you concrete
-
- guidelines for the practical use of Boolean operations.
-
-
-
- REPLACING CONDITIONAL IF-THEN STATEMENTS
-
-
-
- A common use of Boolean operations is to replace a series
-
- of related conditional IF-THEN statements with a streamlined
-
- Boolean statement. If there are a large number of IF-THEN
-
- statements in the subroutine, then the savings in Basic
-
- source code space can be significant.
-
- The easiest example of this concept is when IF-THEN
-
- statements are used to elicit a TRUE or FALSE response, such
-
- as setting flags. Study the following example and note how
-
- IF-THEN statements can be replaced by one line of Boolean
-
- code:
-
-
-
-
-
-
-
-
-
-
-
- -4-
-
-
-
- Do
-
- Print "Select 'Y' to turn flag TRUE"
-
- Repeat
-
- Z$=Inkey$
-
- Until Z$<>""
-
- If Z$="Y" Then
-
- Flag=True
-
- Endif
-
- If Z$<>"Y" Then
-
- Flag=False
-
- Endif
-
- Print "Flag value = ";Flag
-
- Loop
-
-
-
- Using a Boolean operation, this program can be changed to:
-
-
-
- Do
-
- Print "Select 'Y' to turn Flag TRUE"
-
- Repeat
-
- Z$=Inkey$
-
- Until Z$<>""
-
- Flag=(Z$="Y") !BOOLEAN OPERATION
-
- Print "Flag value = ";Flag
-
- Loop
-
-
-
- The REPEAT-UNTIL loop waits until you select a key. If you
-
- select "Y", then Z$="Y" is TRUE and the value of the Flag is
-
-
-
-
-
-
-
-
-
- -5-
-
-
-
- set to negative one(-1). If you select another letter, such
-
- as "N", then Z$="Y" is FALSE and the value of the Flag
-
- variable is set to zero(0).
-
- Okay, this is only a minor change in code; but let's
-
- consider a more lengthy comparison you might have embedded in
-
- a program:
-
-
-
- If Z=10 Then
-
- X=1
-
- Endif
-
- If Z=15 Then
-
- X=2
-
- Endif
-
- If Z=20 Then
-
- X=4
-
- Endif
-
- If Z=25 Then
-
- X=8
-
- Endif
-
-
-
- With Boolean operations to the rescue, this series of
-
- conditional IF-THEN's is reduced to:
-
-
-
- X = ABS((Z=10) + 2*(Z=15) + 4*(Z=20) + 8*(Z=25))
-
-
-
- "Pretty compact now," I would say. One disadvantage is
-
- that this Boolean contraction is visually distracting,
-
-
-
-
-
-
-
-
-
- -6-
-
-
-
- increasing the chances for hidden bugs, compared to the
-
- orderly layout of IF-THEN statements. Fortunately, the GFA
-
- BASIC Editor won't let you get away with incorrect usage of
-
- mathematical symbols. I usually write the program with the
-
- modular IF-THEN statements first. If the program is running
-
- well, I will go back into the source code and apply Boolean
-
- operations where I can, testing the program after each
-
- change, before finally compiling the code.
-
- The calculation of this Boolean operation above would be as
-
- follows:
-
- If Z is not 10,15,20, or 25, then the expression would
-
- be: X equals the absolute value of (0+2*(0)+4*(0)+8*(0)), or
-
- X equals zero.
-
- If Z equals 10, then the expression would be: X equals
-
- the absolute value of ((-1)+2*(0)+4*(0)+8*(0)), or X equals
-
- one.
-
- If Z equals 15, then the expression would be: X equals
-
- the absolute value of (0+2*(-1)+4*(0)+8*(0)), or X equals
-
- two.
-
- If Z equals 20, then the expression would be: X equals
-
- the absolute value of (0+2*(0)+4*(-1)+8*(0)), or X equals
-
- four.
-
- If Z equals 25..., well, I'll let you derive this
-
- condition as a Boolean exercise, because you will be doing
-
- similar calculations in the following practical examples of
-
- an error trapping subroutine and a menu click detection
-
- subroutine.
-
-
-
-
-
-
-
-
-
- -7-
-
-
-
-
-
- ERROR TRAPPING SUBROUTINE
-
-
-
- Study the "***ERROR TRAPPING SUBROUTINE ***" below written
-
- in GFA BASIC. The subroutine catches errors as they occur in
-
- the main program and converts some of the more commonly
-
- occuring error numbers into English text in an Alert Box.
-
- Since the error numbers that I selected for the conversion to
-
- English are random, irregular positive and negative numbers,
-
- I could not quickly dream up an algebraic routine to point to
-
- the English error message by an offset value. I'm not a
-
- mathematical genius! So, normally the Basic programmer would
-
- develop a series of conditional IF-THEN statements to handle
-
- the conversion of an error number to English. A few of these
-
- IF-THEN statements might be as follows:
-
-
-
- If En%=22 Then
-
- Error_message$="FILE ALREADY OPEN"
-
- Endif
-
- If En%=24 Then
-
- Error_message$="FILE NOT OPENED"
-
- Endif
-
- ' !...ONE STATEMENT FOR EACH ERROR NUMBER...
-
- If En%=(-39) Then
-
- Error_message$="MEMORY FULL"
-
- Endif
-
- ' !...AND SO ON...
-
-
-
-
-
-
-
-
-
- -8-
-
-
-
-
-
- Sixteen IF-THEN statements were removed by applying
-
- Boolean logic to the subroutine. It is funny how things
-
- happen, but after I wrote this routine for my GFA BASIC
-
- programs, I discovered that "OPTION E+" in the GFA BASIC
-
- COMPILER inserts a subroutine into compiled GFA BASIC
-
- programs that converts error number messages into English
-
- text!
-
-
-
- ' *** ERROR TRAPPPING SUBROUTINE ***
-
- Procedure Er_trap
-
- Close !CLOSE EVERYTHING
-
- En%=Err !Err RETURNS ERROR NUMBER TO INTEGER VARIABLE En%
-
- '!BOOLEAN OPERATION REPLACES SIXTEEN IF-THEN STATEMENTS
-
- '!Er_dif% VARIABLE IS OFFSET TO ERROR NAME IN DATA SET BELOW
-
- Er_pnt% = Abs((En%=22)+2*(En%=24)+3*(En%=37)+4*(En%=50))
-
- Add Er_pnt%,Abs(5*(En%=48)+6*(En%=51)+7*(En%=52))
-
- Add Er_pnt%,Abs(8*(En%=53)+9*(En%=54)+10*(En%=55))
-
- Add Er_pnt%,Abs(11*(En%=-10)+12*(En%=-11)+13*(En%=-13))
-
- Add Er_pnt%,Abs(14*(En%=-33)+15*(En%=-34)+16*(En%=-39))
-
- If Er_pnt%=0 !IF ERROR NOT COMMON Err#, PRINT THE NUMBER
-
- Error_message$="ERROR # "+Str$(En%)+" OCCURRED"
-
- Alert 1,Error_message$,1,"CONT",B%
-
- Else
-
- Restore Er_data !IF ERROR IS COMMON Err NUMBER,
-
- For I%=1 To Er_pnt% !FIND ENGLISH TEXT IN DATA SET
-
- Read Error_message$
-
-
-
-
-
-
-
-
-
- -9-
-
-
-
- Next I% !AND SEND TEXT TO THE ALERT BOX
-
- Alert 1,Error_message$,1,"CONT",B%
-
- Endif
-
- On Error Gosub Er_trap !RESET ERROR HANDLER
-
- Clr En% !CLEAR ERROR NUMBER VARIABLE
-
- Resume Begin_again !RESTART FILESELECT PROC. IN MAIN PRG
-
- Er_data: !DATA SET OF COMMON ERRORS
-
- Data "FILE ALREADY OPENED","FILE NOT OPENED"
-
- Data "DISKETTE FULL","NOT AN 'R' FILE"
-
- Data "OPEN 'R' FILE | RECORD LENGTH WRONG"
-
- Data "ONLY ONE FIELD PER | OPEN 'R' ALLOWED"
-
- Data "FIELDS LARGER THAN | RECORD LENGTH"
-
- Data "TOO MANY FIELDS (MAX=9)"
-
- Data "GET/PUT FIELDS | STRING LENGTH WRONG"
-
- Data "GET/PUT RECORD | NUMBER WRONG ","WRITE FAULT"
-
- Data "READ FAULT","DISKETTE WRITE PROTECTED"
-
- Data "FILE NOT FOUND","PATH NOT FOUND","MEMORY FULL"
-
- Return
-
-
-
- To demonstrate how the Boolean operation works in this
-
- error trapping subroutine, let's presume that you are
-
- utilizing a FILESELECT subroutine in your program to send a
-
- data array, such as a series of names and addresses, from RAM
-
- to a sequential disk file. You've selected the filename, and
-
- clicked "Enter"; but your diskette cannot receive the data
-
- since the Write-Protection Tab is in the "write-protect-on"
-
- position. This will generate an error number that is trapped
-
-
-
-
-
-
-
-
-
- -10-
-
-
-
- by the error trapping subroutine. The GFA BASIC manual, page
-
- 240 (version 2.0), notes that such an error will generate a
-
- TOS error number of (-13). Therefore, the only TRUE
-
- comparison in the Boolean operation above is (En%=-13). So
-
- the absolute value of 13*(En%=-13) equals ABS(13*(-1)), or
-
- thirteen. All of the other comparisons are FALSE, resulting
-
- in zeros for the rest of the Boolean equation. Therefore,
-
- adding up all of the results of these Boolean comparisons
-
- gives the variable, Er_pnt%, a value of 13. The READ-DATA
-
- subroutine will then put the thirteenth English text error
-
- message into the Alert Box.
-
- If the error number had been (51), then the sixth English
-
- text error message would have been put into the Alert Box.
-
- I hope by now you are catching onto the idea of using
-
- Boolean operations.
-
-
-
- HANDLING MENU CLICKS
-
-
-
- Every GFA BASIC program that uses pull-down menus is
-
- accompanied by a subroutine to conditionally read the "click"
-
- on a menu item, referring the program to another subroutine.
-
- When studying the source code with the GFA BASIC EDITOR, you
-
- will usually see several screenfuls of menu click conditional
-
- IF-THEN statements, such as:
-
-
-
- If Menu(0)=20 Then
-
- Gosub Procedure_three
-
-
-
-
-
-
-
-
-
- -11-
-
-
-
- Endif
-
- ' !... AND SO ON ...
-
-
-
- A whole series of IF-THEN statements can be changed to a
-
- line or two of "ON-(integer variable)-GOSUB-(routine)"
-
- statements using Boolean comparisons. Study the " *** MENU
-
- CLICK DETECTION SUBROUTINE ***" below:
-
-
-
- ' *** MENU CLICK DETECTION SUBROUTINE ***
-
- Procedure Menclick
-
- Q%=Menu(0) !VARIABLE, Q%, HOLDS # OF MENU ITEM CLICKED
-
- ' REPLACE TWELVE IF-ENDIF's WITH BOOLEAN OPERATION
-
- Z%=Abs(1*(Q%=15)+2*(Q%=16)+3*(Q%=18)+4*(Q%=21)
-
- +5*(Q%=22)+6*(Q%=23)+7*(Q%=26)+8*(Q%=27)
-
- +9*(Q%=28)+10*(Q%=29)+11*(Q%=32))+12*(Q%=34))
-
- On Z% Gosub Loadfont,Savefont,Quitprog,Printerreset,
-
- Dlfont,Testfont,Createchar,Editchar,
-
- Copychar,Deletechar,Restorechar,Asciibox
-
- Return
-
-
-
- Now that you are getting more in tune with the Boolean way
-
- of thinking, I'll just give a quick example for the routine
-
- above. Suppose that you clicked the menu item
-
- "Printerreset". The integer variable, Z%, would equal the
-
- absolute value of (1*(0)+2*(0)+3*(0)+4*(-1)+5*(0)...+12*(0)),
-
- or four. The next line of code states, "On four, gosub
-
- Printerreset."
-
-
-
-
-
-
-
-
-
- -12-
-
-
-
-
-
- READING JOYSTICKS AND CHECKING BOUNDARIES
-
-
-
- For this final example, you will find it helpful to refer
-
- to figure 1., which shows all of the ST-joystick position
-
- values. When the joystick is centered, a value of zero is
-
- returned. When the joystick is moved to the upper-right
-
- position, a value of nine is returned.
-
- Let's say you wanted to move a Sprite about the screen, but
-
- wanted to keep it inside a box. The X,Y coordinates of the
-
- upper-left corner of the box are 50,50; and the X,Y
-
- coordinates of the lower-right corner of the box are
-
- 500,150.
-
- The joystick is read to determine which way the Sprite
-
- should move. To move the Sprite, you will be incrementing X
-
- by one for any joystick inputs to the right and you will be
-
- incrementing Y by one for any joystick inputs downward.
-
- Decrementing the X and Y values with joystick inputs will
-
- move the Sprite in the corresponding opposite directions.
-
- To read the joystick, you would have to set up eight
-
- conditional IF-THEN statements, such as:
-
-
-
- If Joystick%=10 Then
-
- X=X+1 !MOVE THE SPRITE DOWN AND RIGHT
-
- Y=Y+1
-
- Endif
-
-
-
-
-
-
-
-
-
-
-
- -13-
-
-
-
- To check the boundaries, you would have to set up four
-
- conditional IF-THEN statements, such as:
-
-
-
- If X>500 Then
-
- X=500 !KEEP 'X' INSIDE RIGHT BORDER
-
- Endif
-
-
-
- That adds about forty lines of IF-THEN-ENDIF statements to
-
- your source code. Study the next example of Boolean logic
-
- and follow the explanation of how it works. This subroutine
-
- is integrated into the brief GFA BASIC program listing
-
- accompanying this tutorial, so you can have fun moving the
-
- Sprite around "The Sprite Corral."
-
-
-
- If S%>0 ! JOYSTICK MOVED FROM CENTER POSTION
-
- '!TESTS FOR 8 JOYSTICK POSITIONS AND CHECKS BOUNDARIES
-
- '!BOOLEAN COMPARISONS REPLACE 12 IF-THEN STATEMENTS
-
- Add X%,(S%>7 And S%<11)*(X%<500)-(S%>3 And S%<7)*(X%>50)
-
- Add Y%,(S% Mod 4=2)*(Y%<150)-(S% Mod 4=1)*(Y%>50)
-
- Endif
-
- Sprite S$,X%,Y% ! POSITIONS SPRITE
-
-
-
- All joystick inputs to the right return the values of 9, 8,
-
- or 10; that is: (S%>7 And S%<11). All joystick inputs to the
-
- left return values that are: (S%>3 And S%<7). All joystick
-
- inputs upward return the values of 5,1, or 9, which are
-
- divisible by four with a remainder of one; that is: (S% Mod
-
-
-
-
-
-
-
-
-
- -14-
-
-
-
- 4=1). All joystick inputs downward return values that are
-
- divisible by four with a remainder of 2: (S% Mod 4=2). These
-
- four comparisons are unique to each of the four cardinal
-
- directions of joystick input.
-
- Let's do the Boolean calculations for a given situation.
-
- The Sprite is at X,Y coordinates of 100,125. You move the
-
- joystick to the right, returning a value of S%=8. The
-
- comparisons (S%>7 And S%<11), (X%<500), (X%>50), (Y%<150),
-
- and (Y%>50) are TRUE and are assigned the value of (-1). All
-
- other Boolean comparisons are FALSE and are assigned the
-
- value of (0). The calculation is then:
-
- Add X%,(-1*-1) - (0*-1) or Add X%,1
-
- Add Y%,(0*-1) - (0*-1) or Add Y%,0
-
- This moves the Sprite to the right by one with new X,Y
-
- coordinates of 101,125.
-
- To show how boundaries are checked, keep pushing the Sprite
-
- to the right until the X coordinate is 500. Stop. Now try
-
- to move the Sprite to the right, returning a joystick
-
- position value of S%=8. Again the comparisons (S%>7 And
-
- S%<11), (X%>50), (Y%<150), and (Y%>50) are TRUE and are
-
- assigned a value of (-1). But now the comparison (X%<500) is
-
- FALSE and is assigned a value of (0). The other comparisons
-
- remain FALSE. The calculation is now:
-
- Add X%,(-1*0) - (0*-1) or Add X%,0
-
- Add Y%,(0*-1) - (0*-1) or Add Y%,0
-
- The Sprite will not move past the right X boundary of 500
-
- despite your joystick input to the right.
-
-
-
-
-
-
-
-
-
- -15-
-
-
-
- A more complicated and final situation might find the
-
- Sprite at X,Y coordinates of 100,150. You push the joystick
-
- downward and to the left, returning a joystick position value
-
- of S%=6. The comparisons (S% Mod 4=2), (S%>3 And S%<7),
-
- (X%>50), (X%<500), and (Y%>50) are TRUE and are assigned a
-
- value of (-1). The other comparisons are FALSE and are
-
- assigned a value of (0). The Boolean calculations are:
-
- Add X%,(0*-1) - (-1*-1) or Add X%,(-1)
-
- Add Y%,(-1*0) - (0*-1) or Add Y%,0
-
- The Sprite moves to the left, but is unable to move below
-
- the lower Y boundary of 150. The new Sprite X,Y coordinates
-
- are 99,150.
-
- With the assistance of this tutorial, the beginner GFA
-
- BASIC programmer should have a better understanding of
-
- Boolean operations and will be able to employ them in future
-
- programming efforts to reduce the object code length and
-
- improve the speed of program execution. Of course, Boolean
-
- algebra is an unusual way of calculating equations, so don't
-
- feel overwhelmed if you have to read this tutorial over
-
- again. I had to read that section in my algebra book three
-
- times.
-
-
-
- GFA BASIC LISTING
-
-
-
- ' *** MOVE SPRITE WITH JOYSTICK IN PORT 1 ***
-
- Sp$=Mki$(1)+Mki$(1)+Mki$(0)+Mki$(0)+Mki$(1) ! DEFINE SPRITE
-
- For I%=1 To 16
-
-
-
-
-
-
-
-
-
- -16-
-
-
-
- Sp$=Sp$+Mki$(0)+Mki$(65535)
-
- Next I%
-
- Deffill 3,2,6 !DRAW THE BOX TO HOLD THE SPRITE
-
- Pbox 50,49,514,164
-
- Print At(30,14);Chr$(27);"c2";"The Sprite Corral";
-
- X%=50 !PUT SPRITE IN BOX
-
- Y%=50
-
- Print At(1,24);"Press any key to quit";
-
- Hidem
-
- '
-
- Repeat !Peek $FFFC02 = QUICK READ JOYSTICK POSITION
-
- @Readjoy(Peek(&HFFFC02))
-
- Until Inkey$<>"" !PRESS ANY KEY TO QUIT GFA BASIC ROUTINE
-
- Out 4,&H8 ! TURN MOUSE BACK ON WHEN EXIT PROGRAM
-
- '
-
- Procedure Readjoy(S%)!PASS VALUE Peek $FFFC02 TO VARIABLE S%
-
- If S%>0 ! JOYSTICK MOVED FROM CENTER POSTION
-
- ' TESTS FOR 8 JOYSTICK POSITIONS AND CHECKS BOUNDARIES
-
- ' !REPLACES 12 IF-THEN STATEMENTS
-
- Add X%,(S%>7 And S%<11)*(X%<500)-(S%>3 And S%<7)*(X%>50)
-
- Add Y%,(S% Mod 4=2)*(Y%<150)-(S% Mod 4=1)*(Y%>50)
-
- Endif
-
- Vsync ! REMOVES ANIMATION FLICKER
-
- Sprite S$,X%,Y% ! POSITIONS SPRITE
-
- Return
-
-
-
-
-
-
-
-
-
-
-
-